﻿namespace ScrumLite.Services.Tests
{
    using System;
    using System.Collections.Generic;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using ScrumLite.Services.Contracts;
    using Rhino.Mocks;
    using System.Linq;
    using System.Collections.ObjectModel;
    using System.Globalization;

    [TestClass]
    public class LinqRequestServiceFixture
    {
        MockRepository mocks;
        [TestInitialize]
        public void Initialize()
        {
            this.mocks = new MockRepository();
        }

        [TestMethod()]
        public void ShouldSaveRequests()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            List<ScrumLite.Data.Request> actual = new List<ScrumLite.Data.Request>();
            bool shouldUpdateWorkArea = false;

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            // repeat the expectation twice because we will save two requests, hence expect two calls to Update
            Expect.Call(() => store.Update(null, false))
                .Callback(new Func<ScrumLite.Data.Request, bool, bool>((r, b) => { actual.Add(r); shouldUpdateWorkArea = b; return true; }))
                .Repeat.Times(2);
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);
            Request[] requests = new Request[] { 
                new Request { Id = Guid.NewGuid(), Committed = true, Moniker = 100, Notes = "Some notes", Priority = 1, Requestor = "requestor", Status = RequestStatus.Taken, Title = "Some title", Weight = 2, DueOn = new DateTime(2008, 12, 31) },
                new Request { Id = Guid.NewGuid(), Committed = false, Moniker = 101, Notes = "Some notes", Priority = 2, Requestor = null, Status = RequestStatus.Waiting, Title = "Another title", Weight = null, DueOn = new DateTime(2009, 12, 31)  },
            };
            Guid projectId = Guid.NewGuid();
            service.SaveRequests(projectId.ToString(), requests);

            Assert.AreEqual(requests.Length, actual.Count);
            for(int i=0; i<requests.Length; i++)
            {
                Assert.AreEqual(requests[i].Id, actual[i].id);
                Assert.AreEqual(requests[i].Moniker, actual[i].moniker);
                Assert.AreEqual(requests[i].Notes, actual[i].notes);
                Assert.AreEqual(requests[i].Order, actual[i].order);
                Assert.AreEqual(requests[i].Priority, actual[i].priority);
                Assert.AreEqual(requests[i].Requestor, actual[i].requestor);
                Assert.AreEqual((byte)requests[i].Status, actual[i].en_status);
                Assert.AreEqual(requests[i].Title, actual[i].title);
                Assert.AreEqual(requests[i].Weight, actual[i].weight);
                Assert.AreEqual(requests[i].CreatedOn, actual[i].createdOn);
                Assert.AreEqual(requests[i].Committed, actual[i].committed);
                Assert.AreEqual(requests[i].DueOn, actual[i].dueOn);
                Assert.IsFalse(shouldUpdateWorkArea);
            }            
        }

        [TestMethod]
        public void ShouldCalculateDaysToDue()
        {
            Request request = new Request();

            request.DueOn = DateTime.Today.Add(new TimeSpan(100, 0, 0, 0));

            TimeSpan ts1 = new TimeSpan(99, 0, 0, 0);
            TimeSpan ts2 = new TimeSpan(101, 0, 0, 0);

            Assert.IsTrue(ts1.CompareTo(request.TimeSpanToDue) < 0);
            Assert.IsTrue(ts2.CompareTo(request.TimeSpanToDue) > 0);
        }

        [TestMethod]
        public void ShouldAddRequest()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.Request actual = null;

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.Add(null))
                .Callback(new Func<ScrumLite.Data.Request, bool>(r => { actual = r; return true; }));
            Expect.Call(store.RetrieveLastMoniker(Guid.Empty))
                .Return(99)                
                .Callback(new Func<Guid, bool>(r => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Guid projectId = Guid.NewGuid();
            Guid workAreaId = Guid.NewGuid();
            Guid requestId = Guid.NewGuid();

            // a workarea
            ScrumLite.Data.WorkArea expectedWorkArea = new ScrumLite.Data.WorkArea
            {
                fk_project = projectId,
                name = "WorkArea1",
                id = workAreaId
            };

            List<ScrumLite.Services.Contracts.WorkArea> workAreas = new List<WorkArea>() { new WorkArea() { Id = expectedWorkArea.id.ToString(), Name = expectedWorkArea.name } };

            Request expected = new Request { Id = requestId, Committed = true, Moniker = 100, Notes = "Some notes", Priority = 1, Requestor = "requestor", Status = RequestStatus.Taken, Title = "Some title", Weight = 2, CreatedOn = new DateTime(2008, 11,23), DueOn = new DateTime(2008,12,31), WorkAreas = workAreas.ToArray() };

            service.AddRequest(projectId.ToString(), expected);

            Assert.AreEqual(expected.Id, actual.id);
            Assert.AreEqual(expected.Moniker, actual.moniker);
            Assert.AreEqual(expected.Notes, actual.notes);
            Assert.AreEqual(expected.Order, actual.order);
            Assert.AreEqual(expected.Priority, actual.priority);
            Assert.AreEqual(expected.Requestor, actual.requestor);
            Assert.AreEqual((byte)expected.Status, actual.en_status);
            Assert.AreEqual(expected.Title, actual.title);
            Assert.AreEqual(expected.Weight, actual.weight);
            Assert.AreEqual(DateTime.Now.Date, actual.createdOn.Date);
            Assert.AreEqual(expected.Committed, actual.committed);
            Assert.AreEqual(expected.DueOn, actual.dueOn);

            //Check WorkArea            
            Assert.AreEqual(expectedWorkArea.id, actual.RequestWorkAreas[0].fk_workarea);
        }

        [TestMethod]
        public void ShouldAddRequestAndReturnMonikerNumber()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.Request actual = null;

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.Add(null))
                .Callback(new Func<ScrumLite.Data.Request, bool>(r => { actual = r; return true; }));
            Expect.Call(store.RetrieveLastMoniker(Guid.Empty))
                .Return(99)
                .Callback(new Func<Guid, bool>(r => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Guid projectId = Guid.NewGuid();
            Request expected = new Request { Id = Guid.NewGuid(), Committed = true, Moniker = 0, Notes = "Some notes", Priority = 1, Requestor = "requestor", Status = RequestStatus.Taken, Title = "Some title", Weight = 2, CreatedOn = new DateTime(2008, 11, 23), WorkAreas = new WorkArea[] { } };
            int moniker = service.AddRequest(projectId.ToString(), expected);

            Assert.AreEqual(expected.Id, actual.id);
            Assert.AreEqual(expected.Notes, actual.notes);
            Assert.AreEqual(expected.Order, actual.order);
            Assert.AreEqual(expected.Priority, actual.priority);
            Assert.AreEqual(expected.Requestor, actual.requestor);
            Assert.AreEqual((byte)expected.Status, actual.en_status);
            Assert.AreEqual(expected.Title, actual.title);
            Assert.AreEqual(expected.Weight, actual.weight);
            Assert.AreEqual(DateTime.Now.Date, actual.createdOn.Date);
            Assert.AreEqual(expected.Committed, actual.committed);
            Assert.AreEqual(100, moniker);
        }

        [TestMethod]
        public void ShouldUpdateRequest()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.Request actual = null;
            bool shouldUpdateWorkArea = false;

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.Update(null, false))
                .Callback(new Func<ScrumLite.Data.Request, bool, bool>((r, b) => { actual = r; shouldUpdateWorkArea = b; return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Guid projectId = Guid.NewGuid();
            Guid workAreaId = Guid.NewGuid();

            // a workarea
            ScrumLite.Data.WorkArea expectedWorkArea = new ScrumLite.Data.WorkArea
            {
                fk_project = projectId,
                name = "WorkArea1",
                id = workAreaId
            };

            List<ScrumLite.Services.Contracts.WorkArea> workAreas = new List<WorkArea>() { new WorkArea() { Id = expectedWorkArea.id.ToString(), Name = expectedWorkArea.name } };

            Request expected = new Request { Id = Guid.NewGuid(), Committed = true, Moniker = 100, Notes = "Some notes", Priority = 1, Requestor = "requestor", Status = RequestStatus.Taken, Title = "Some title", Weight = 2, CreatedOn = new DateTime(2008, 11, 23), DueOn = new DateTime(2008, 12, 31), WorkAreas = workAreas.ToArray() };
            service.UpdateRequest(projectId.ToString(), expected);

            Assert.AreEqual(expected.Id, actual.id);
            Assert.AreEqual(expected.Moniker, actual.moniker);
            Assert.AreEqual(expected.Notes, actual.notes);
            Assert.AreEqual(expected.Order, actual.order);
            Assert.AreEqual(expected.Priority, actual.priority);
            Assert.AreEqual(expected.Requestor, actual.requestor);
            Assert.AreEqual((byte)expected.Status, actual.en_status);
            Assert.AreEqual(expected.Title, actual.title);
            Assert.AreEqual(expected.Weight, actual.weight);
            Assert.AreEqual(DateTime.Now.Date, actual.createdOn.Date);
            Assert.AreEqual(expected.Committed, actual.committed);
            Assert.AreEqual(expected.DueOn, actual.dueOn);

            //Check WorkArea
            Assert.IsTrue(shouldUpdateWorkArea);
            Assert.AreEqual(expectedWorkArea.id, actual.RequestWorkAreas[0].fk_workarea);
        }

        [TestMethod]
        public void ShouldSetOrderIfStatusIsCompleted()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.Request actual = null;
            int expectedOrder = 100;
            
            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.Update(null, false))
                .Callback(new Func<ScrumLite.Data.Request, bool, bool>((r, b) => { actual = r; return true; }));
            Expect.Call(store.RetrieveLastOrder(Guid.Empty))
                .Return(expectedOrder-1)
                .Callback(new Func<Guid, bool>(r => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Guid projectId = Guid.NewGuid();
            Request expected = new Request { Id = Guid.NewGuid(), Committed = true, Moniker = 100, Notes = "Some notes", Priority = 1, Requestor = "requestor", Status = RequestStatus.Completed, Title = "Some title", Weight = 2, CreatedOn = new DateTime(2008, 11, 23), WorkAreas = new WorkArea[] {} };
            service.UpdateRequest(projectId.ToString(), expected);

            Assert.AreEqual(expectedOrder, actual.order);
        }

        [TestMethod]
        public void ShouldGetRequestByRequestProjectIdAndWorkArea()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.Request[] expected = new ScrumLite.Data.Request[] { new ScrumLite.Data.Request { id = Guid.NewGuid(), committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 3, title = "Some title", weight = 2, createdOn = new DateTime(2008, 11, 23), order = 2, fk_project = Guid.NewGuid(), dueOn = new DateTime(2008,12,31) } };

            string workAreaName = "workAreaName";
            Guid projectId = Guid.NewGuid();
            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveRequests(projectId, workAreaName))
                .Return(expected)
                .Callback(new Func<Guid, string, bool>((a, b) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Collection<Request> actual = service.GetRequests(projectId.ToString(), workAreaName);

            Assert.AreEqual(1, actual.Count);
            Assert.AreEqual(expected.ToList()[0].id, actual.First().Id);
            Assert.AreEqual(expected.ToList()[0].moniker, actual.First().Moniker);
            Assert.AreEqual(expected.ToList()[0].notes, actual.First().Notes);
            Assert.AreEqual(expected.ToList()[0].order, actual.First().Order);
            Assert.AreEqual(expected.ToList()[0].priority, actual.First().Priority);
            Assert.AreEqual(expected.ToList()[0].requestor, actual.First().Requestor);
            Assert.AreEqual(expected.ToList()[0].en_status, (byte)actual.First().Status);
            Assert.AreEqual(expected.ToList()[0].title, actual.First().Title);
            Assert.AreEqual(expected.ToList()[0].weight, actual.First().Weight);
            Assert.AreEqual(expected.ToList()[0].createdOn, actual.First().CreatedOn.Date);
            Assert.AreEqual(expected.ToList()[0].committed, actual.First().Committed);
            Assert.AreEqual(expected.ToList()[0].dueOn, actual.First().DueOn);
        }

        [TestMethod]
        public void ShouldGetRequestByRequestProjectIdAndMoniker()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.Request expected = new ScrumLite.Data.Request { id = Guid.NewGuid(), committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 3, title = "Some title", weight = 2, createdOn = new DateTime(2008, 11, 23), order = 2, fk_project = Guid.NewGuid(), dueOn =  new DateTime(2008,12,31) };
            
            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveRequest(null, 0))
                .Return(expected)
                .Callback(new Func<string, int, bool>((a, b) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Guid projectId = Guid.NewGuid();
            Request actual = service.GetRequest(projectId.ToString(), 10);

            Assert.AreEqual(expected.id, actual.Id);
            Assert.AreEqual(expected.moniker, actual.Moniker);
            Assert.AreEqual(expected.notes, actual.Notes);
            Assert.AreEqual(expected.order, actual.Order);
            Assert.AreEqual(expected.priority, actual.Priority);
            Assert.AreEqual(expected.requestor, actual.Requestor);
            Assert.AreEqual(expected.en_status, (byte)actual.Status);
            Assert.AreEqual(expected.title, actual.Title);
            Assert.AreEqual(expected.weight, actual.Weight);
            Assert.AreEqual(expected.createdOn, actual.CreatedOn.Date);
            Assert.AreEqual(expected.committed, actual.Committed);
            Assert.AreEqual(expected.dueOn, actual.DueOn);
        }

        [TestMethod]
        public void ShouldGetOpenedRequestsForAProject()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            ScrumLite.Data.Request[] expected = new ScrumLite.Data.Request[] { 
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 1, title = "Some title", weight = 2, dueOn = new DateTime(2008,12,31) },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = false, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 2, title = "Another title", weight = null, dueOn = new DateTime(2008,12,31) },
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveOpenedRequests(Guid.Empty))
                .Return(expected)
                .Callback(new Func<Guid, bool>((a) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Request[] actual = service.GetOpenedRequests(projectId.ToString());

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id, actual[i].Id);
                Assert.AreEqual(expected[i].moniker, actual[i].Moniker);
                Assert.AreEqual(expected[i].notes, actual[i].Notes);
                Assert.AreEqual(expected[i].order, actual[i].Order);
                Assert.AreEqual(expected[i].priority, actual[i].Priority);
                Assert.AreEqual(expected[i].requestor, actual[i].Requestor);
                Assert.AreEqual(expected[i].en_status, (byte)actual[i].Status);
                Assert.AreEqual(expected[i].title, actual[i].Title);
                Assert.AreEqual(expected[i].weight, actual[i].Weight);
                Assert.AreEqual(expected[i].createdOn, actual[i].CreatedOn);
                Assert.AreEqual(expected[i].committed, actual[i].Committed);
                Assert.AreEqual(expected[i].fk_project, projectId);
                Assert.AreEqual(expected[i].dueOn, actual[i].DueOn);

            }            
        }

        [TestMethod]
        public void ShouldGetCommittedRequestsForAProject()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            ScrumLite.Data.Request[] expected = new ScrumLite.Data.Request[] { 
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 1, title = "Some title", weight = 2 },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = false, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 2, title = "Another title", weight = null },
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveCommittedRequests(Guid.Empty))
                .Return(expected)
                .Callback(new Func<Guid, bool>((a) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Request[] actual = service.GetCommittedRequests(projectId.ToString());

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id, actual[i].Id);
                Assert.AreEqual(expected[i].moniker, actual[i].Moniker);
                Assert.AreEqual(expected[i].notes, actual[i].Notes);
                Assert.AreEqual(expected[i].order, actual[i].Order);
                Assert.AreEqual(expected[i].priority, actual[i].Priority);
                Assert.AreEqual(expected[i].requestor, actual[i].Requestor);
                Assert.AreEqual(expected[i].en_status, (byte)actual[i].Status);
                Assert.AreEqual(expected[i].title, actual[i].Title);
                Assert.AreEqual(expected[i].weight, actual[i].Weight);
                Assert.AreEqual(expected[i].createdOn, actual[i].CreatedOn);
                Assert.AreEqual(expected[i].committed, actual[i].Committed);
                Assert.AreEqual(expected[i].fk_project, projectId);

            }
        }

        [TestMethod]
        public void ShouldDeleteRequest()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid actual = Guid.Empty;

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.Delete(Guid.Empty))
                .Callback(new Func<Guid, bool>(g => { actual = g; return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Guid expected = Guid.NewGuid();
            service.DeleteRequest(expected);

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ShouldGetWorkAreasForProject()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            ScrumLite.Data.WorkArea[] expected = new ScrumLite.Data.WorkArea[] {
                new ScrumLite.Data.WorkArea() { id = Guid.NewGuid(), name = "WorkArea1", fk_project = projectId },
                new ScrumLite.Data.WorkArea() { id = Guid.NewGuid(), name = "WorkArea2", fk_project = projectId }
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveWorkAreas(Guid.Empty))
                .Return(expected)
                .Callback(new Func<Guid, bool>(g => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            WorkArea[] actual = service.GetWorkAreas(projectId.ToString());

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id, new Guid( actual[i].Id ));
                Assert.AreEqual(expected[i].name, actual[i].Name);
            }
        }

        [TestMethod]
        public void ShouldGetAWorkArea()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            Guid id = Guid.NewGuid();
            ScrumLite.Data.WorkArea[] expected = new ScrumLite.Data.WorkArea[] {
                new ScrumLite.Data.WorkArea() { id = id, name = "WorkArea1", fk_project = projectId },
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveWorkAreas(Guid.Empty))
                .Return(expected)
                .Callback(new Func<Guid, bool>(g => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            WorkArea actual = service.GetWorkArea(projectId.ToString(),id);

            Assert.AreEqual(expected.Length, 1);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id.ToString(), actual.Id);
                Assert.AreEqual(expected[i].name, actual.Name);
            }
        }

        [TestMethod]
        public void ShouldSaveAWorkArea()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            List<ScrumLite.Data.WorkArea> actual = new List<ScrumLite.Data.WorkArea>();

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            // repeat the expectation twice because we will save two requests, hence expect two calls to Update
            Expect.Call(() => store.SaveWorkArea(null))
                .Callback(new Func<ScrumLite.Data.WorkArea, bool>(r => { actual.Add(r); return true; }))
                .Repeat.Times(2);
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);
            WorkArea[] workAreas = new WorkArea[] { 
                new WorkArea { Id = Guid.NewGuid().ToString(), Name="WorkArea1" },
                new WorkArea { Id = Guid.NewGuid().ToString(), Name="WorkArea2"},
            };
            Guid projectId = Guid.NewGuid();
            foreach (WorkArea wa in workAreas)
            {
                service.SaveWorkArea(wa, projectId);
            }

            Assert.AreEqual(workAreas.Length, actual.Count);
            for (int i = 0; i < workAreas.Length; i++)
            {
                Assert.AreEqual(workAreas[i].Id, actual[i].id.ToString());
                Assert.AreEqual(workAreas[i].Name, actual[i].name);
            }        
        }

        [TestMethod]
        public void ShouldGetWorkAreasForARequest()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            ScrumLite.Data.WorkArea[] expected = new ScrumLite.Data.WorkArea[] {
                new ScrumLite.Data.WorkArea { id = Guid.NewGuid(), name = "WorkArea 1" },
                new ScrumLite.Data.WorkArea { id = Guid.NewGuid(), name = "WorkArea 2" }
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveWorkAreas(Guid.Empty, 0))
                .Return(expected)
                .Callback(new Func<Guid, int, bool>( (r, m) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            WorkArea[] actual = service.GetWorkAreasByMoniker(projectId.ToString(), 100);

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id.ToString(), actual[i].Id);
                Assert.AreEqual(expected[i].name, actual[i].Name);
            }
        }

        [TestMethod]
        public void ShouldGetWorkAreasGroupedByWeight()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            Guid wa1 = Guid.NewGuid();
            Guid wa2 = Guid.NewGuid();
            Dictionary<Guid,ScrumLite.Data.WorkAreaReport> expected = new Dictionary<Guid, ScrumLite.Data.WorkAreaReport>();
            expected[wa1] = new ScrumLite.Data.WorkAreaReport { TotalWeight =10, Name = "WorkArea1", DeliverableCount = 3, RequestCount = 4 };
            expected[wa2] = new ScrumLite.Data.WorkAreaReport { TotalWeight =2, Name = "WorkArea2", DeliverableCount = 2, RequestCount = 7 };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveWorkAreasGroupedByWeight(Guid.Empty))
                .Return(expected)
                .Callback(new Func<Guid, bool>(g => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            WorkAreaWeight[] actual = service.GetWorkAreasGroupByWeight(projectId.ToString());

            Assert.AreEqual(expected.Count, actual.Length);
            for (int i = 0; i < expected.Count; i++)
            {
                Assert.AreEqual(expected.Keys.ToList()[i], actual[i].Id);
                Assert.AreEqual(expected.Values.ToList()[i].TotalWeight, actual[i].Weight);
                Assert.AreEqual(expected.Values.ToList()[i].Name, actual[i].Name );
                Assert.AreEqual(expected.Values.ToList()[i].DeliverableCount, actual[i].Deliverables);
                Assert.AreEqual(expected.Values.ToList()[i].RequestCount, actual[i].Requests);
            }
        }

        [TestMethod]
        public void ShouldGetRequestStatusList()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            ScrumLite.Data.RequestStatus[] expected = new ScrumLite.Data.RequestStatus[] {
                new ScrumLite.Data.RequestStatus() { key = 1, value = "Status 1" },
                new ScrumLite.Data.RequestStatus() { key = 2, value = "Status 2" }
            };
            
            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveRequestStatusList())
                .Return(expected)
                .Callback(new Func<bool>(() => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Dictionary<string,string> actual = service.GetStatusList();

            Assert.AreEqual(expected.Length, actual.Count);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].key.ToString(CultureInfo.CurrentCulture), actual.Keys.ToList()[i]);
                Assert.AreEqual(expected[i].value.ToString(CultureInfo.CurrentCulture), actual.Values.ToList()[i]);
            }
        }

        [TestMethod()]
        public void ShouldAssignWorkAreasToARequest()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            object actual = null;

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.AssignWorkAreas(Guid.Empty, 0, null))
                .Callback(new Func<Guid, int, string[], bool>((p, m, w) => { actual = new { Moniker = m, ProjectId = p, WorkAreas = w }; return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);
            Guid projectId = Guid.NewGuid();
            int moniker = 10;
            string[] areas = new string[] { "Area1", "Area2" };
            service.AssignWorkAreas(projectId.ToString(), moniker, areas);

            Assert.AreEqual(projectId, (Guid)actual.GetPropertyValue("ProjectId"));
            Assert.AreEqual(moniker, (int)actual.GetPropertyValue("Moniker"));
            Assert.AreEqual(areas, (string[])actual.GetPropertyValue("WorkAreas"));
        }

        [TestMethod()]
        public void ShouldNotAssignNullWorkAreasToARequest()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            object actual = new object();

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.AssignWorkAreas(Guid.Empty, 0, null))
                .Callback(new Func<Guid, int, string[], bool>((p, m, w) => { actual = null; return false; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);
            Guid projectId = Guid.NewGuid();
            int moniker = 10;
            string[] areas = null;
            service.AssignWorkAreas(projectId.ToString(), moniker, areas);

            Assert.IsNull(actual);
        }

        [TestMethod]
        public void ShouldSetPrioritiesBatch()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid[] requestIds = new Guid[] { Guid.NewGuid(), Guid.NewGuid() };
            Guid[] actual = null;

            Expect.Call(() => store.UpdateRequestsPriority(new Guid[] { }))
                .Callback(new Func<Guid[], bool>((r) => { actual = r; return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);
            service.SetPriorities(requestIds);

            Assert.AreEqual(requestIds.Length, actual.Length);
        }

        [TestMethod]
        public void ShouldGetWeeklyWeight()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();

            DateTime dateForFirstWeek = DateTime.Parse("2008-01-01",CultureInfo.CurrentCulture);
            DateTime dateForSecondWeek = DateTime.Parse("2008-01-06",CultureInfo.CurrentCulture);

            ScrumLite.Data.Request[] expected = new ScrumLite.Data.Request[] { 
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 100, notes = "Some notes 1", priority = 1, requestor = "requestor", en_status = 1, title = "Some title", weight = 2, completedOn = dateForFirstWeek },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = false, moniker = 101, notes = "Some notes 2", priority = 2, requestor = null, en_status = 2, title = "Another title", weight = 1, completedOn = dateForSecondWeek},
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = false, moniker = 101, notes = "Some notes 3", priority = 2, requestor = null, en_status = 2, title = "Yet Another title", weight = 2, completedOn = dateForSecondWeek}
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveCompletedRequests(Guid.Empty))
                .Return(expected)
                .Callback(new Func<Guid, bool>(g => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Dictionary<int, int> actual = service.GetWeeklyWeight(projectId.ToString());

            Assert.IsTrue(actual.ContainsKey(1));
            Assert.IsTrue(actual.ContainsKey(2));
            Assert.AreEqual(2, actual[1]);
            Assert.AreEqual(3, actual[2]);
        }
        
        [TestMethod]
        public void ShouldGetRequestByStatus()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
                        
            Dictionary<byte?, int> statusExpected = new Dictionary<byte?, int>();
            statusExpected.Add(1, 23);
            statusExpected.Add(2, 42);
            
            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveCountRequestsByStatus(projectId))
                .Return(statusExpected)
                .Callback(new Func<Guid, bool>(g => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Dictionary<RequestStatus, int> actual = service.GetRequestsByStatus(projectId.ToString());

            Assert.IsNotNull(actual);
            Assert.AreEqual(2, actual.Count);
            Assert.AreEqual(23, actual[RequestStatus.Taken]);
            Assert.AreEqual(42, actual[RequestStatus.Waiting]);
        }


        [TestMethod]
        public void ShouldGetDaysToExpire()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            ScrumLite.Data.Request[] expected = new ScrumLite.Data.Request[] { 
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 1, title = "Some title", weight = 2, dueOn = DateTime.Today.AddDays(30) },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = false, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 2, title = "Another title", weight = null, dueOn = DateTime.Today.AddDays(30) },
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveOpenedRequests(projectId))
                .Return(expected)
                .Callback(new Func<Guid, bool>((a) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Request[] actual = service.GetOpenedRequests(projectId.ToString());

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id, actual[i].Id);
                Assert.AreEqual(expected[i].moniker, actual[i].Moniker);
                Assert.AreEqual(expected[i].notes, actual[i].Notes);
                Assert.AreEqual(expected[i].order, actual[i].Order);
                Assert.AreEqual(expected[i].priority, actual[i].Priority);
                Assert.AreEqual(expected[i].requestor, actual[i].Requestor);
                Assert.AreEqual(expected[i].en_status, (byte)actual[i].Status);
                Assert.AreEqual(expected[i].title, actual[i].Title);
                Assert.AreEqual(expected[i].weight, actual[i].Weight);
                Assert.AreEqual(expected[i].createdOn, actual[i].CreatedOn);
                Assert.AreEqual(expected[i].committed, actual[i].Committed);
                Assert.AreEqual(expected[i].fk_project, projectId);
                Assert.AreEqual(expected[i].dueOn, actual[i].DueOn);
                Assert.AreEqual("30", actual[i].DaysToDue.Trim());
            } 
        }

        [TestMethod]
        public void ShouldNotGetDaysToExpireInClosedRequests()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            ScrumLite.Data.Request[] expected = new ScrumLite.Data.Request[] { 
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 4, title = "Some title", weight = 2, dueOn = DateTime.Today.AddDays(30), completedOn = DateTime.Today.AddDays(20) }
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(store.RetrieveRequests(projectId, String.Empty))
                .Return(expected)
                .Callback(new Func<Guid,string, bool>((a,b) => { return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Collection<Request> actual = service.GetRequests(projectId.ToString(), String.Empty);

            Assert.AreEqual(expected.Length, actual.Count());
            for (int i = 0; i < expected.Length; i++)
            {
                Assert.AreEqual(expected[i].id, actual[i].Id);
                Assert.AreEqual(expected[i].moniker, actual[i].Moniker);
                Assert.AreEqual(expected[i].notes, actual[i].Notes);
                Assert.AreEqual(expected[i].order, actual[i].Order);
                Assert.AreEqual(expected[i].priority, actual[i].Priority);
                Assert.AreEqual(expected[i].requestor, actual[i].Requestor);
                Assert.AreEqual(expected[i].en_status, (byte)actual[i].Status);
                Assert.AreEqual(expected[i].title, actual[i].Title);
                Assert.AreEqual(expected[i].weight, actual[i].Weight);
                Assert.AreEqual(expected[i].createdOn, actual[i].CreatedOn);
                Assert.AreEqual(expected[i].committed, actual[i].Committed);
                Assert.AreEqual(expected[i].completedOn, actual[i].CompletedOn);
                Assert.AreEqual(expected[i].fk_project, projectId);
                Assert.AreEqual(expected[i].dueOn, actual[i].DueOn);
                Assert.AreEqual("0", actual[i].DaysToDue.Trim());
            }
        }

        [TestMethod]
        public void ShouldCleanCommittedRequests()
        {
            ScrumLite.Data.IRequestStore store = this.mocks.DynamicMock<ScrumLite.Data.IRequestStore>();
            Guid projectId = Guid.NewGuid();
            RequestStatus[] statusList= new RequestStatus[3] {RequestStatus.Blocked, RequestStatus.Completed, RequestStatus.Postponed };
            ScrumLite.Data.Request[] actual = new ScrumLite.Data.Request[] { 
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 100, notes = "Some notes", priority = 1, requestor = "requestor", en_status = 4, title = "Some title", weight = 2 },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 2, title = "Another title", weight = null },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 1, title = "Another title", weight = null },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 3, title = "Another title", weight = null },
                new ScrumLite.Data.Request { id = Guid.NewGuid(), fk_project= projectId, committed = true, moniker = 101, notes = "Some notes", priority = 2, requestor = null, en_status = 5, title = "Another title", weight = null }
            };

            // set an expectation that will do a callback and set the argument 
            // to a local member to perform Asserts later
            Expect.Call(() => store.CleanCommittedRequestByStatus(projectId, new byte[3] {3, 4, 5 }))
                .Callback(new Func<Guid, byte[], bool>((a, b) => { foreach (ScrumLite.Data.Request r in actual) {if (b.Contains(r.en_status.Value)) {r.committed = false;}}; return true; }));
            mocks.ReplayAll();

            LinqRequestsService service = new LinqRequestsService(store);

            Assert.AreEqual(5, actual.Count(r => r.committed == true));
            service.CleanCommitted(projectId.ToString(), statusList);

            Assert.IsNotNull(actual);
            Assert.AreEqual(2, actual.Count(r => r.committed == true));
        }
    }     
      
    public static class ReflectionExtensions {
        public static object GetPropertyValue(this object instance, string propertyName)
        {
            return instance.GetType().GetProperties().Where(p => p.Name == propertyName).SingleOrDefault().GetValue(instance, null);
        }
    }
}
